﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using DL.Net;
using NetGameRunning;
using UnityEngine;

//https://www.zhihu.com/question/20626441
//TODO 存在问题是 _responseResult _pendingTasks 好像不互通了
namespace Logic.Handler
{
    //容器
    //ConcurrentDictionary 这里所有都是在主线程做的
    //所以这里直接用字典就行了
    public class ResponseResultContainer : SingletonNoMono<ResponseResultContainer>
    {
        private readonly Dictionary<int, ResponseResult> _responseResult = new();

        private readonly Dictionary<int, TaskCompletionSource<ResponseResult>> _pendingTasks = new();

        private readonly ResponseResultHandler _responseResultHandler = new();

        public void AddResponseResult(ResponseMessage msg)
        {
            var result = ResponseMessageEvent(msg);
            lock (_responseResult)
            {
                if (_responseResult.ContainsKey(msg.Data.Seq))
                {
                    Debug.Log($"存在一个ResponseResult{msg.Data.Seq}消息还未被取出。现在丢弃！");
                    _responseResult[msg.Data.Seq] = result;
                }
                else
                {
                    lock (_pendingTasks)
                    {
                        // 如果有等待此ID的TaskCompletionSource，设置结果并移除
                        if (_pendingTasks.TryGetValue(msg.Data.Seq, out var tcs))
                        {
                            _pendingTasks.Remove(msg.Data.Seq);
                            tcs.SetResult(result);
                            return;
                        }
                    }
                    _responseResult.TryAdd(msg.Data.Seq, result);
                }
            }
        }

        public async Task<ResponseResult> WaitForResponseAsync(int seq, TimeSpan timeSpan,
            CancellationToken cancellationToken = default)
        {
            if (_responseResult.TryGetValue(seq, out var result))
            {
                _responseResult.Remove(seq);
                return await Task.FromResult(result);
            }

            TaskCompletionSource<ResponseResult> tcs = new();

            if (!_pendingTasks.TryAdd(seq, tcs))
            {
                throw new InvalidOperationException("无法添加等待任务。");
            }

            var timeoutTask = Task.Delay(timeSpan, cancellationToken);
            var completedTask = await Task.WhenAny(tcs.Task, timeoutTask);
            if (completedTask == tcs.Task)
            {
                return tcs.Task.Result;
            }
            else
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancellationToken);
                }
                else
                {
                    throw new TimeoutException($"等待ResponseResult超时，序列号：{seq}");
                }
            }
        }

        private ResponseResult ResponseMessageEvent(ResponseMessage msg)
        {
            return _responseResultHandler.ResponseResultHandle(msg);
        }

        public void LogContainerState([CallerMemberName] string name = null)
        {
            Debug.Log($"{name}--->PendingTasks Count: {_pendingTasks.Count}, ResponseResult Count: {_responseResult.Count}");
        }
    }
}